﻿using System;

namespace TypeInfo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("{0,-10} {1,-10} {2,-30} {3,-30}", "Type", "Bytes", "Min Value", "Max Value");
            Console.WriteLine(new string('-', 80));
            PrintTypeInfo<sbyte>("sbyte");
            PrintTypeInfo<byte>("byte");
            PrintTypeInfo<short>("short");
            PrintTypeInfo<ushort>("ushort");
            PrintTypeInfo<int>("int");
            PrintTypeInfo<uint>("uint");
            PrintTypeInfo<long>("long");
            PrintTypeInfo<ulong>("ulong");
            PrintTypeInfo<float>("float");
            PrintTypeInfo<double>("double");
            PrintTypeInfo<decimal>("decimal");

            // 等待用户按下回车键
            Console.WriteLine("\n按回车键退出...");
            Console.ReadLine();
        }

        static void PrintTypeInfo<T>(string typeName) where T : struct, IComparable, IConvertible, IFormattable
        {
            Console.WriteLine("{0,-10} {1,-10} {2,-30} {3,-30}", 
                typeName, 
                System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)), 
                GetMinValue<T>(), 
                GetMaxValue<T>());
        }

        static string GetMinValue<T>() where T : struct, IComparable, IConvertible, IFormattable
        {
            return typeof(T).IsValueType ? Convert.ChangeType(GetMinValueInternal<T>(), typeof(T)).ToString() : "N/A";
        }

        static string GetMaxValue<T>() where T : struct, IComparable, IConvertible, IFormattable
        {
            return typeof(T).IsValueType ? Convert.ChangeType(GetMaxValueInternal<T>(), typeof(T)).ToString() : "N/A";
        }

        static object GetMinValueInternal<T>() where T : struct
        {
            if (typeof(T) == typeof(sbyte)) return sbyte.MinValue;
            if (typeof(T) == typeof(byte)) return byte.MinValue;
            if (typeof(T) == typeof(short)) return short.MinValue;
            if (typeof(T) == typeof(ushort)) return ushort.MinValue;
            if (typeof(T) == typeof(int)) return int.MinValue;
            if (typeof(T) == typeof(uint)) return uint.MinValue;
            if (typeof(T) == typeof(long)) return long.MinValue;
            if (typeof(T) == typeof(ulong)) return ulong.MinValue;
            if (typeof(T) == typeof(float)) return float.MinValue;
            if (typeof(T) == typeof(double)) return double.MinValue;
            if (typeof(T) == typeof(decimal)) return decimal.MinValue;
            throw new ArgumentException("Unsupported type");
        }

        static object GetMaxValueInternal<T>() where T : struct
        {
            if (typeof(T) == typeof(sbyte)) return sbyte.MaxValue;
            if (typeof(T) == typeof(byte)) return byte.MaxValue;
            if (typeof(T) == typeof(short)) return short.MaxValue;
            if (typeof(T) == typeof(ushort)) return ushort.MaxValue;
            if (typeof(T) == typeof(int)) return int.MaxValue;
            if (typeof(T) == typeof(uint)) return uint.MaxValue;
            if (typeof(T) == typeof(long)) return long.MaxValue;
            if (typeof(T) == typeof(ulong)) return ulong.MaxValue;
            if (typeof(T) == typeof(float)) return float.MaxValue;
            if (typeof(T) == typeof(double)) return double.MaxValue;
            if (typeof(T) == typeof(decimal)) return decimal.MaxValue;
            throw new ArgumentException("Unsupported type");
        }
    }
}